<template>
  <div class="flex w-full rounded-[var(--border-radius-small)] bg-[var(--text-n9)] p-[16px]">
    <div class="and-or">
      <CrmTag
        type="primary"
        theme="light"
        :color="{ color: 'var(--primary-6)' }"
        class="z-[1] w-[38px] cursor-pointer"
        @click="changeAllOr"
      >
        {{ formModel.searchMode === 'AND' ? 'and' : 'or' }}
      </CrmTag>
    </div>
    <div class="min-w-0 flex-1">
      <n-form ref="formRef" :model="formModel">
        <div
          v-for="(item, listIndex) in formModel.list"
          :key="item.dataIndex || `filter_item_${listIndex}`"
          class="flex items-start gap-[8px]"
        >
          <n-form-item
            :path="`list[${listIndex}].dataIndex`"
            :rule="[{ required: true, message: t('common.value.nameNotNull') }]"
            class="dataIndex-col block flex-1 overflow-hidden"
          >
            <n-select
              v-model:value="item.dataIndex"
              value-field="dataIndex"
              :disabled="props.readonly"
              filterable
              :placeholder="t('common.pleaseSelect')"
              :options="currentOptions(item.dataIndex as string)"
              @update:value="(val) => dataIndexChange(val, listIndex)"
            />
          </n-form-item>
          <n-form-item :path="`list[${listIndex}].operator`" class="block w-[120px]">
            <n-select
              v-model:value="item.operator"
              :disabled="!item.dataIndex || props.readonly"
              :options="getOperatorOptions(item.type, item.dataIndex as string)"
              @update:value="operatorChange(item, listIndex)"
            />
          </n-form-item>
          <n-form-item
            :path="`list[${listIndex}].value`"
            class="block flex-[1.5] overflow-hidden"
            :rule="getRules(item)"
          >
            <CrmTimeRangePicker
              v-if="
                [FieldTypeEnum.TIME_RANGE_PICKER,FieldTypeEnum.DATE_TIME].includes(item.type)  &&
                [OperatorEnum.DYNAMICS, OperatorEnum.FIXED].includes(item.operator as OperatorEnum)
              "
              v-model:value="item.value"
              :time-range-type="item.operator"
              :disabled="isValueDisabled(item)"
              @update:value="valueChange"
            />
            <n-date-picker
              v-else-if=" ([FieldTypeEnum.TIME_RANGE_PICKER,FieldTypeEnum.DATE_TIME].includes(item.type) &&
                ![OperatorEnum.DYNAMICS, OperatorEnum.FIXED].includes(item.operator as OperatorEnum))"
              v-model:value="item.value"
              :type="item.operator === OperatorEnum.BETWEEN ? 'datetimerange' : 'datetime'"
              clearable
              :disabled="isValueDisabled(item)"
              class="w-full"
              :default-time="item.operator === OperatorEnum.BETWEEN ? [undefined, '23:59:59'] : undefined"
              @update:value="valueChange"
            />
            <CrmInputNumber
              v-else-if="
                item.type === FieldTypeEnum.INPUT_NUMBER ||
                (item.type === FieldTypeEnum.INPUT_MULTIPLE &&
                  [OperatorEnum.COUNT_LT, OperatorEnum.COUNT_GT].includes(item.operator as OperatorEnum))
              "
              v-model:value="item.value"
              clearable
              :disabled="isValueDisabled(item)"
              :placeholder="item.numberProps?.placeholder ?? t('common.pleaseInput')"
              v-bind="{
                min: item.numberProps?.min,
              }"
              class="w-full"
              @update:value="valueChange"
            />
            <CrmTagInput
              v-else-if="
                item.type === FieldTypeEnum.INPUT_MULTIPLE &&
                ![OperatorEnum.COUNT_LT, OperatorEnum.COUNT_GT].includes(item.operator as OperatorEnum)
              "
              v-model:value="item.value"
              clearable
              :disabled="isValueDisabled(item)"
              class="w-full"
              @update:value="valueChange"
            />

            <CrmDataSource
              v-else-if="[FieldTypeEnum.DATA_SOURCE, FieldTypeEnum.DATA_SOURCE_MULTIPLE].includes(item.type)"
              v-model:value="item.value"
              v-model:rows="item.selectedRows"
              v-bind="{
                ...item.dataSourceProps,
                dataSourceType:item?.dataSourceProps?.dataSourceType as FieldDataSourceTypeEnum,
              }"
              :disabled="isValueDisabled(item)"
              @change="valueChange"
            />
            <n-select
              v-else-if="
                [
                  FieldTypeEnum.SELECT,
                  FieldTypeEnum.SELECT_MULTIPLE,
                  FieldTypeEnum.RADIO,
                  FieldTypeEnum.CHECKBOX,
                ].includes(item.type)
              "
              v-model:value="item.value"
              clearable
              max-tag-count="responsive"
              :disabled="isValueDisabled(item)"
              :placeholder="t('common.pleaseSelect')"
              v-bind="item.selectProps"
              :multiple="item.type === FieldTypeEnum.SELECT_MULTIPLE || item.selectProps?.multiple"
              @update:value="valueChange"
            />
            <CrmCitySelect
              v-else-if="item.type === FieldTypeEnum.LOCATION"
              v-model:value="item.value"
              :placeholder="t('common.pleaseInput')"
              :disabled="isValueDisabled(item)"
              clearable
              multiple
              check-strategy="parent"
              @update:value="valueChange"
            />
            <CrmIndustrySelect
              v-else-if="item.type === FieldTypeEnum.INDUSTRY"
              v-model:value="item.value"
              :placeholder="t('common.pleaseInput')"
              :disabled="isValueDisabled(item)"
              clearable
              multiple
              check-strategy="parent"
              @update:value="valueChange"
            />
            <CrmUserTagSelector
              v-else-if="
                [
                  FieldTypeEnum.DEPARTMENT,
                  FieldTypeEnum.DEPARTMENT_MULTIPLE,
                  FieldTypeEnum.MEMBER,
                  FieldTypeEnum.MEMBER_MULTIPLE,
                ].includes(item.type)
              "
              v-model:value="item.value"
              v-model:selected-list="item.selectedUserList"
              multiple
              :disabled="isValueDisabled(item)"
              :drawer-title="t('crmFormDesign.selectDataSource')"
              :api-type-key="MemberApiTypeEnum.FORM_FIELD"
              :member-types="
                [FieldTypeEnum.MEMBER, FieldTypeEnum.MEMBER_MULTIPLE].includes(item.type)
                  ? [
                      {
                        label: t('menu.settings.org'),
                        value: MemberSelectTypeEnum.ORG,
                      },
                    ]
                  : [
                      {
                        label: t('menu.settings.org'),
                        value: MemberSelectTypeEnum.ONLY_ORG,
                      },
                    ]
              "
              :disabled-node-types="
                [FieldTypeEnum.MEMBER, FieldTypeEnum.MEMBER_MULTIPLE].includes(item.type)
                  ? [DeptNodeTypeEnum.ORG, DeptNodeTypeEnum.ROLE]
                  : [DeptNodeTypeEnum.USER, DeptNodeTypeEnum.ROLE]
              "
            />
            <CrmTreeSelect
              v-else-if="item.type === FieldTypeEnum.TREE_SELECT"
              v-model:value="item.value"
              v-model:contain-child-ids="item.containChildIds"
              :disabled="isValueDisabled(item)"
              :placeholder="t('common.pleaseSelect')"
              :type="item.treeSelectProps?.options ? 'custom' : 'department'"
              v-bind="item.treeSelectProps"
              @update:value="valueChange"
            />
            <CrmUserSelect
              v-else-if="item.type === FieldTypeEnum.USER_SELECT"
              v-model:value="item.value"
              value-field="id"
              label-field="name"
              :disabled="isValueDisabled(item)"
              multiple
              :options="userOptionsList"
              max-tag-count="responsive"
              @update:value="valueChange"
            />

            <n-input
              v-else
              v-model:value="item.value"
              allow-clear
              :disabled="isValueDisabled(item)"
              :maxlength="255"
              :placeholder="t('advanceFilter.inputPlaceholder')"
              v-bind="item.inputProps"
              @update:value="valueChange"
            />
          </n-form-item>
          <n-form-item
            v-if="item.showScope"
            :path="`list[${listIndex}].scope`"
            class="block w-[150px] flex-initial overflow-hidden"
          >
            <n-select
              v-model:value="item.scope"
              :disabled="item.scopeProps?.disabled"
              :options="scopeOptions"
              multiple
            />
          </n-form-item>
          <n-button
            :disabled="(props.keepOneLine && formModel.list.length === 1) || props.readonly"
            class="outline--secondary px-[7px]"
            @click="handleDeleteItem(listIndex)"
          >
            <template #icon>
              <CrmIcon type="iconicon_minus_circle1" :size="16" />
            </template>
          </n-button>
        </div>
      </n-form>
      <div class="flex items-center justify-between">
        <n-tooltip v-if="!props.readonly" :delay="300" :disabled="!props.maxFilterFieldAddTooltip || !isDisabledAdd">
          <template #trigger>
            <n-button type="primary" :disabled="isDisabledAdd" text class="w-[fit-content]" @click="handleAddItem">
              <template #icon>
                <n-icon><Add /></n-icon>
              </template>
              {{ t('advanceFilter.addCondition') }}
            </n-button>
          </template>
          {{ props.maxFilterFieldAddTooltip }}
        </n-tooltip>
        <slot name="addButtonRight"></slot>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { FormInst, NButton, NDatePicker, NForm, NFormItem, NIcon, NInput, NSelect, NTooltip } from 'naive-ui';
  import { Add } from '@vicons/ionicons5';

  import { OperatorEnum } from '@lib/shared/enums/commonEnum';
  import { FieldDataSourceTypeEnum, FieldTypeEnum } from '@lib/shared/enums/formDesignEnum';
  import { MemberApiTypeEnum, MemberSelectTypeEnum } from '@lib/shared/enums/moduleEnum';
  import { DeptNodeTypeEnum } from '@lib/shared/enums/systemEnum';
  import { useI18n } from '@lib/shared/hooks/useI18n';
  import { scrollIntoView } from '@lib/shared/method/dom';

  import CrmIndustrySelect from '@/components/pure/crm-industry-select/index.vue';
  import CrmInputNumber from '@/components/pure/crm-input-number/index.vue';
  import CrmTag from '@/components/pure/crm-tag/index.vue';
  import CrmTagInput from '@/components/pure/crm-tag-input/index.vue';
  import CrmTreeSelect from '@/components/pure/crm-tree-select/index.vue';
  import CrmCitySelect from '@/components/business/crm-city-select/index.vue';
  import CrmDataSource from '@/components/business/crm-data-source-select/index.vue';
  import CrmTimeRangePicker from '@/components/business/crm-time-range-picker/index.vue';
  import CrmUserSelect from '@/components/business/crm-user-select/index.vue';
  import CrmUserTagSelector from '@/components/business/crm-user-tag-selector/index.vue';

  import { getUserOptions } from '@/api/modules';

  import { operatorOptionsMap, scopeOptions } from '../index';
  import type { FilterForm, FilterFormItem } from '../type';
  import { getDefaultOperator } from '../utils';
  import { SelectMixedOption } from 'naive-ui/es/select/src/interface';

  const { t } = useI18n();

  const props = defineProps<{
    configList: FilterFormItem[];
    customList?: FilterFormItem[];
    keepOneLine?: boolean; // 至少保留一行
    readonly?: boolean;
    noFilterOption?: boolean; // 第一列取消过滤
    maxFilterFieldNumber?: number; // 最大限制条件数量
    maxFilterFieldAddTooltip?: string; // 添加最大限制文本提示
  }>();

  const formModel = defineModel<FilterForm>('formModel', {
    required: true,
  });
  // 过滤
  const formRef = ref<FormInst | null>(null);

  function valueIsArray(listItem: FilterFormItem) {
    return (
      [
        FieldTypeEnum.SELECT_MULTIPLE,
        FieldTypeEnum.DEPARTMENT_MULTIPLE,
        FieldTypeEnum.MEMBER_MULTIPLE,
        FieldTypeEnum.DATA_SOURCE_MULTIPLE,
        FieldTypeEnum.DATA_SOURCE,
      ].includes(listItem.type) ||
      listItem.selectProps?.multiple ||
      listItem.cascaderProps?.multiple ||
      (listItem.type === FieldTypeEnum.INPUT_MULTIPLE &&
        ![OperatorEnum.COUNT_LT, OperatorEnum.COUNT_GT].includes(listItem.operator as OperatorEnum)) ||
      (listItem.type === FieldTypeEnum.DATE_TIME && listItem.operator === OperatorEnum.BETWEEN)
    );
  }

  function changeAllOr() {
    if (props.readonly) return;
    formModel.value.searchMode = formModel.value.searchMode === 'AND' ? 'OR' : 'AND';
  }

  function isValueDisabled(item: FilterFormItem) {
    return props.readonly || !item.dataIndex || ['EMPTY', 'NOT_EMPTY'].includes(item.operator as string);
  }

  // 第一列下拉数据
  const currentOptions = computed(() => {
    const allOptions = [...props.configList, ...(props.customList || [])];
    if (props.noFilterOption) {
      return () => allOptions.map((item) => ({ ...item, label: t(item.title as string) }));
    }
    const formItems = formModel.value.list;

    return (currentDataIndex: string) => {
      const usedDataIndices = new Set(
        formItems.filter((item) => item.dataIndex !== currentDataIndex).map((item) => item.dataIndex)
      );

      return allOptions
        .filter(({ dataIndex }) => !usedDataIndices.has(dataIndex))
        .map((item) => ({ ...item, label: t(item.title as string) }));
    };
  });

  const getListItemByDataIndex = (dataIndex: string): FilterFormItem | undefined => {
    const mergedList: FilterFormItem[] = [...props.configList, ...(props.customList || [])];

    return mergedList.find((item) => item.dataIndex === dataIndex);
  };

  const userOptionsList = ref<SelectMixedOption[]>([]);
  async function getUserOption() {
    try {
      userOptionsList.value = await getUserOptions();
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }

  onMounted(() => {
    // 初始化视图回显
    formModel.value.list.forEach((item, index) => {
      if (item.dataIndex) {
        const listItem = getListItemByDataIndex(item.dataIndex);
        if (!listItem) return;
        const currentListItem: FilterFormItem = {
          ...listItem,
          ...item,
          type: listItem.type,
          ...(listItem.showScope ? { scope: item.scope ?? listItem.scope } : undefined),
        };
        formModel.value.list[index] = currentListItem;
      }
    });
    getUserOption();
  });

  // 改变第一列值
  const dataIndexChange = (dataIndex: string, index: number) => {
    const listItem = getListItemByDataIndex(dataIndex);

    if (!listItem) return;

    const isArray = valueIsArray(listItem);
    const currentListItem: FilterFormItem = {
      ...listItem,
      value: isArray ? [] : undefined,
      ...(listItem.showScope ? { scope: listItem.scope } : undefined),
    };

    // 显式类型注解，避免类型过深
    const currentFormList = formModel.value.list as FilterFormItem[];

    currentFormList[index] = currentListItem;

    // 如果当前操作符没有值，自动赋默认
    const hasNoOperator = !currentFormList[index].operator?.length;

    if (hasNoOperator) {
      const options = listItem?.operatorOption?.length
        ? listItem.operatorOption
        : operatorOptionsMap[currentFormList[index].type] || [];

      const optionsValueList = options.map((optionItem: { value: string; label: string }) => optionItem.value);

      currentFormList[index].operator = getDefaultOperator(optionsValueList);
    }
  };

  // 获取操作符号
  function getOperatorOptions(type: FieldTypeEnum, dataIndex: string) {
    const listItem = getListItemByDataIndex(dataIndex);
    return (listItem?.operatorOption?.length ? listItem.operatorOption : operatorOptionsMap[type])?.map((e) => {
      return {
        ...e,
        label: t(e.label),
      };
    });
  }

  // 删除筛选项
  function handleDeleteItem(index: number) {
    formModel.value.list.splice(index, 1);
  }

  // 符号变化
  function operatorChange(item: FilterFormItem, index: number) {
    if (item.type === FieldTypeEnum.DATE_TIME) {
      formModel.value.list[index].value = null;
    } else {
      formModel.value.list[index].value = valueIsArray(item) ? [] : null;
    }

    if (formModel.value.list[index]?.selectedRows && formModel.value.list[index]?.selectedRows?.length) {
      formModel.value.list[index].selectedRows = [];
    }

    if (formModel.value.list[index]?.selectedUserList && formModel.value.list[index]?.selectedUserList?.length) {
      formModel.value.list[index].selectedUserList = [];
    }

    formRef.value?.restoreValidation();
  }

  function valueChange() {
    formRef.value?.validate();
  }

  // 获取校验规则
  function getRules(item: FilterFormItem) {
    if (isValueDisabled(item)) {
      return undefined;
    }
    if (item.rule) return item.rule;
    if ([FieldTypeEnum.TIME_RANGE_PICKER, FieldTypeEnum.DATE_TIME].includes(item.type)) {
      return [
        {
          validator: (rule: any, value: string | number) => {
            if (!value && value !== 0) return new Error(t('common.value.notNull'));
            if (item.operator === OperatorEnum.DYNAMICS) {
              // 动态模式需要校验数字部分
              const [time, num, unit] = (value as string).split(',');
              if (time === 'CUSTOM') {
                return !!Number(num) || new Error(t('common.value.notNull'));
              }
            }
          },
        },
      ];
    }
    return [
      {
        required: true,
        message: t('common.value.notNull'),
      },
    ];
  }

  const isDisabledAdd = computed(() =>
    props.maxFilterFieldNumber
      ? formModel.value.list?.length >= props.maxFilterFieldNumber
      : formModel.value.list?.length === [...props.configList, ...(props.customList ?? [])].length
  );

  function validateForm(cb: (res?: Record<string, any>) => void) {
    formRef.value?.validate(async (errors) => {
      if (errors) {
        scrollIntoView(document.querySelector('.n-form-item-blank--error'), { block: 'center' });
        return;
      }
      if (typeof cb === 'function') {
        cb();
      }
    });
  }

  // 添加筛选项
  function handleAddItem() {
    validateForm(() => {
      const item = {
        key: '',
        type: FieldTypeEnum.INPUT,
        value: null,
      };
      formModel.value.list.push(item);
    });
  }

  defineExpose({
    formRef,
    validateForm,
  });
</script>

<style lang="less" scoped>
  .and-or {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-right: 16px;
    height: auto;
    &::after {
      content: '';
      position: absolute;
      top: 0;
      left: 50%;
      width: 1px;
      height: 100%;
      background-color: var(--text-n8);
      transform: translateX(-50%);
    }
    :deep(.n-tag__content) {
      margin: 0 auto;
    }
  }
  :deep(.n-form-item-feedback-wrapper) {
    min-height: 8px;
  }
</style>
